/*
 * 脚本执行顺序:
 * 1. 修改配置文件
 * 2. 写入日志
 * 3. 打包文件
 */
import inquirer from 'inquirer'
import fs from 'fs-extra'
import path from 'path'
import { fileURLToPath } from 'url'
import { exec } from 'child_process'
import iconv from 'iconv-lite'

class buildManage {
    constructor(option) {
        this.buildPath = option.buildPath // 打包配置文件路径
        this.projectPath = option.projectPath // 项目路径
		this.longTime = option.longTime  // 打包间隔时间
		this.agent_ids = option.agent_ids  // 打包列表
		this.index = 0	// 打包列表索引
		this.state = true  // 打包状态
		this.timer = null,	// 打包间隔定时器
		this.awaitTimer = null
		this.awaitTime = option.longTime / 1000
		this.createTime = this.getFileName()
    }
    start() {
		if(this.agent_ids.length > 10) {
			console.log('>>>>>>>>>>>>>>>>>>>>>提示: 打包数量最高为10, uni打包限制每个账号10次打包')
			return
		}

		if(this.agent_ids.length === 0) {
			console.log('当前打包id数量为空, 无需打包')
			return
		} else {
			// 命令行交互，返回值是promise對象
			inquirer.prompt([
				{
					type: 'list',
					message: `是否开始打包,首个打包agent_id: ${this.agent_ids[this.index]}`,
					name: 'state',
					choices: ['是', '否']
				}
			]).then(res => {
				if(res.state === '是') {
					this.handleStart()
				}
			})
		}
    }
	async handleStart() {
		if(!this.state) {
			if(this.timer !== null) {
				clearTimeout(this.timer)
				this.timer =null
			}
			return
		}

		if(this.index >= this.agent_ids.length) {
			console.log('\n>>>>>>>>>>>>>>>>>>>>>全部打包完成<<<<<<<<<<<<<<<<<<<<<\n')

			fs.appendFileSync(`./log.txt`, `\n>>>>>>>>>>>>>>>>>>>>>全部打包完成<<<<<<<<<<<<<<<<<<<<<\n`)
			return
		}

		if(this.state) {
			const id = this.agent_ids[this.index]
			console.log('>>>>>>>>>>>>>>>>>>>>>开始打包\n')
			console.log(`>>>>>>>>>>>>>>>>>>>>>当前索引：${this.index}\n`)
			console.log(`>>>>>>>>>>>>>>>>>>>>>当前客户agent_id: ${id}\n`)

			const res = await this.commandSpawn(`cli pack --config ${this.buildPath}`, id)

			fs.appendFileSync(`./log.txt`, res.message)
			
			if(res.code === 200) {
				// 当数量为0时，打包完成，停止打包
				if(res.end) {
					console.log('\n>>>>>>>>>>>>>>>>>>>>>全部打包完成<<<<<<<<<<<<<<<<<<<<<\n')
					return
				}

				this.awaitTime = option.longTime / 1000

				this.awaitTimer = setInterval(() => {
					if(this.awaitTime === 0) {
						clearInterval(this.awaitTimer)
						this.awaitTimer = null
						return
					}
					console.log(`距离下次打包时间: ${this.awaitTime}`)
					this.awaitTime--
				}, 1000)

				// 否则继续打包
				this.timer = setTimeout(() => {
					clearInterval(this.awaitTimer)
					this.awaitTimer = null
					this.handleStart()
				}, this.longTime)
			} else {
				this.state = false
			}
		}
	}
	getFileName() {
		const now = new Date()
		const year = now.getFullYear()
		const month = now.getMonth() + 1
		const day = now.getDate()
		const hour = now.getHours()
		const minute = now.getMinutes()
		const second = now.getSeconds()
		const len = this.agent_ids.length
		const time = `${year}-${month}-${day}/${hour}:${minute}:${second}-${len}`
		return time
	}
	commandSpawn(arg, id) {
		return new Promise(async (resolve, reject) => {
			// 修改配置文件
			const configResult = await this.handleSetConfig(id)
			if(configResult.code === 200) {
				fs.appendFileSync(`./log.txt`, `${configResult.message}`)
				fs.writeFileSync(`./build/user${id}.txt`, '')
				const childProcess = exec(arg, { encoding: 'binary' })
				
				// 输出流
				childProcess.stdout.on('data', data => {
					const result = iconv.decode(data, 'cp936')
					console.log(result)
					fs.appendFileSync(`./build/user${id}.txt`, `${result} \n\n`)
				})
	
				// 错误信息
				childProcess.stderr.on('data', data => {
					console.log('>>>>>>>>>>>>>>>>>>>>>错误信息')
					const result = iconv.decode(data, 'cp936')
					console.log(result)
					resolve({
						code: 400,
						message: `打包失败, agent_id:${id} \n ${result} \n\n`,
						end: false
					})
				})
	
				// 结束
				childProcess.on('exit', () => {
					const index = this.agent_ids.findIndex(item => item === id)
					const last = this.agent_ids.length - index - 1
					console.log(`>>>>>>>>>>>>>>>>>>>>>打包完成>>>>>>>>>>>>>>>>>>>>>剩余待打包数量: ${last} \n\n`)
					this.index++
					resolve({
						code: 200,
						message: `agent_id:${id}, 打包完成-----结束 \n\n`,
						end: last === 0
					})
				})
			} else {
				resolve({
					code: 400,
					message: `${configResult.message}`,
					end: false
				})
			}
		})
	}
	handleSetConfig(id) {
		return new Promise((resolve, reject) => {
			try {
				// 读取配置
				const p = path.resolve(this.projectPath, 'env.js')
				const content = fs.readFileSync(p, 'utf8')
				const regex = /export const agent_id = ([\d\w]+)/
				const newContent = content.replace(regex, `export const agent_id = ${id}`)
				fs.writeFileSync(p, newContent, 'utf8')
				console.log('>>>>>>>>>>>>>>>>>>>>>配置修改成功\n')
				resolve({
					code: 200,
					message: '修改配置成功\n'
				})
			} catch {
				console.log('>>>>>>>>>>>>>>>>>>>>>配置修改失败\n')
				resolve({
					code: 400,
					message: `修改配置失败, agent_id:${id}\n`
				})
			}
		})
	}
}

export default buildManage